import { _decorator, color, Component, EventKeyboard, input, Input, instantiate, Label, math, Node, Prefab, Sprite, SpriteFrame } from 'cc';
import { Config } from './config'
import { generate } from './generate'
import { GameState, ItemColor, KeyboardType } from './enums'
import { nextShape } from './nextShape';
const { ccclass, property } = _decorator;


@ccclass('main')
export class main extends Component {
    private items: ItemColor[][] = [][Config.col]; //颜色列表，表示当前表格各方块颜色
    private boxGenerate: generate | null = null;
    private shapes: Node[][] = [][Config.col]; //Prefab控件列表
    private currShape: number[][] = []; //当前图形
    private currColor: ItemColor = null;//当前图形的颜色
    private nextShape: number[][] = [] //下一图形信息
    private nextColor: ItemColor = null;
    private shapeTimer = null;//定时器
    private default: ItemColor[] = [];
    private score: number = 0;
    private overCallback: () => void;

    @property({ type: Prefab })
    public box: Prefab | null = null;

    @property({ type: SpriteFrame })
    private colors: SpriteFrame[] = []

    @property({ type: nextShape })
    private nextShapeController: nextShape | null = null;

    @property({ type: Label })
    public scoreLabel: Label | null = null; //分数

    start() {

    }

    update(deltaTime: number) {

    }

    setGameOverCallback(callback: () => void) {
        this.overCallback = callback;
    }

    //键盘事件
    setKeyboardActive(active: boolean) {
        if (active) {
            //键盘按下事件
            input.on(Input.EventType.KEY_DOWN, this.keyboardDownCallback, this);
        } else {
            input.off(Input.EventType.KEY_DOWN, this.keyboardDownCallback, this);
        }
    }

    //获取下一个下落的图形
    getNextShape() {
        this.getCurrShapeAndColor();
        if (!this.isMove(this.currShape)) {
            //当前放不下了，游戏结束
            if (this.shapeTimer !== null) clearInterval(this.shapeTimer);
            this.overCallback();
            return;
        }
        this.refreshItemColor();
        this.shareGenerate()
        this.nextShapeController.changeNext(this.nextColor, this.nextShape);
        this.shapeTimer = setInterval(() => {
            if (!this.shapeLeftOrRightOrDown([1, 0])) {
                clearInterval(this.shapeTimer);
                this.clearRowShape();
            }
        }, Config.shapeDownTime);
    }

    //清除已满一行的格子
    clearRowShape() {
        var set = new Set();
        var a = -1, b = 0;
        for (var i = Config.row - 1; i >= 0; i--) {
            var num = 0;
            for (var j = 0; j < Config.col; j++) {
                if (this.items[i][j] != ItemColor.DEFAULT) {
                    b = i;
                    num++;
                }
            }
            if (num == Config.col) {
                set.add(i);
                if (a == -1) a = i;
                for (var j = 0; j < Config.col; j++) {
                    this.items[i][j] = ItemColor.DEFAULT;
                }
            }
        }

        //将清空的行上方的方块向下移
        if (a != -1) {
            for (var j = a - 1; j >= 0; j--) {
                if (!set.has(j)) {
                    for (var q = 0; q < Config.col; q++) {
                        this.items[a][q] = this.items[j][q];
                    }
                    a--;
                }
            }
            this.items[0] = this.default;
            this.score += set.size * 10;
            this.scoreLabel.string = '' + this.score;
        }

        //执行完清空操作后，获取下一图形
        this.getNextShape();
    }

    //更新表格当前颜色 isClear是否清空当前颜色
    refreshItemColor(isClear: boolean = false) {
        for (var i = 0; i < this.currShape.length; i++) {
            this.items[this.currShape[i][0]][this.currShape[i][1]] = (isClear ? ItemColor.DEFAULT : this.currColor);
        }
    }

    //控件移动
    moveShape(copyShape: number[][], arr: number[]) {
        for (var i = 0; i < copyShape.length; i++) {
            copyShape[i][0] += arr[0];
            copyShape[i][1] += arr[1];
        }
    }

    //是否能移动
    isMove(copyShape: number[][]): Boolean {
        var res = true;
        for (var i = 0; i < copyShape.length; i++) {
            var shape = copyShape[i];
            if (shape[0] < 0 || shape[1] < 0 || shape[1] >= Config.col || shape[0] >= Config.row || this.items[shape[0]][shape[1]] !== ItemColor.DEFAULT) res = false;
        }
        return res;
    }

    //控件变换
    changeShape(callback: (copyShape: number[][]) => void) {
        var copyShape = [];
        var res = false;
        for (var i = 0; i < this.currShape.length; i++) {
            copyShape.push([this.currShape[i][0], this.currShape[i][1]]);
        }

        this.refreshItemColor(true);
        callback(copyShape);
        if (this.isMove(copyShape)) {
            this.currShape = copyShape;
            res = true;
        }
        this.refreshItemColor(false);
        this.shareGenerate();
        return res;
    }

    //控件向左,向右,向下移动
    shapeLeftOrRightOrDown(num: number[]): boolean {
        return this.changeShape((copyShape) => {
            this.moveShape(copyShape, num);
        });
    }

    //控件旋转
    shapeRotate() {
        this.changeShape((copyShape) => {
            var sumX = 0, sumY = 0;
            for (var i = 0; i < copyShape.length; i++) {
                sumX += copyShape[i][0];
                sumY += copyShape[i][1];
            }

            var x = Math.round(sumX / this.currShape.length), y = Math.round(sumY / this.currShape.length);

            for (var i = 0; i < copyShape.length; i++) {
                var item = copyShape[i];
                var a = item[0], b = item[1];
                var xT = (x - item[0]), yT = (y - item[1]);

                a = a + xT - yT;
                b = b + xT + yT;

                item[0] = a;
                item[1] = b;
            }
        })
    }

    //键盘按下事件
    keyboardDownCallback(event: EventKeyboard) {
        var keyCode = event.keyCode;
        if (keyCode === KeyboardType.LEFT as number) {
            //控件向左移动
            this.shapeLeftOrRightOrDown([0, -1]);
        } else if (keyCode == KeyboardType.RIGHT as number) {
            //控件向右移动
            this.shapeLeftOrRightOrDown([0, 1]);
        } else if (keyCode == KeyboardType.ROTATE as number) {
            //控件旋转,为了防止旋转图案过快，加个冷却时间
            this.setKeyboardActive(false);
            this.shapeRotate();
            setTimeout(() => {
                this.setKeyboardActive(true);
            }, 350);
        } else if (keyCode == KeyboardType.SPEED as number) {
            //长按加速下落
            this.setKeyboardActive(false);
            this.shapeLeftOrRightOrDown([2, 0]);
            setTimeout(() => {
                this.setKeyboardActive(true);
            }, 150);
        }
    }

    //获取当前图形和颜色
    getCurrShapeAndColor() {
        this.currShape = this.nextShape;
        this.currColor = this.nextColor;
        //获取下一图形
        var shareIndex = Math.floor(Math.random() * Config.shapes.length);
        this.nextShape = Config.shapes[shareIndex];
        this.nextColor = Math.floor(Math.random() * this.colors.length) + 1;
    }

    //初始化数据
    initData() {
        this.setKeyboardActive(false);

        var a = 0, b = 0;  //节点的x轴和y轴距离
        this.items = [];
        this.shapes = [];
        this.node.removeAllChildren();
        this.score = 0;
        for (var j = 0; j < Config.col; j++) this.default.push(ItemColor.DEFAULT);

        //获取第一个节点
        var shareIndex = Math.floor(Math.random() * Config.shapes.length);
        this.nextShape = Config.shapes[shareIndex];
        this.nextColor = Math.floor(Math.random() * this.colors.length) + 1;
        this.nextShapeController.nextItemInit(this.colors, this.nextColor, this.nextShape);

        for (var i = 0; i < Config.row; i++, b += Config.blockHeight) {
            this.items.push([]);
            this.shapes.push([]);
            a = 0

            for (var j = 0; j < Config.col; j++, a += Config.blockWidth) {
                this.items[i].push(ItemColor.DEFAULT);

                var newNode = instantiate(this.box);
                this.node.addChild(newNode);
                newNode.setPosition(a, b);
                this.shapes[i].push(newNode);
            }
        }

        if (this.shapeTimer !== null) clearInterval(this.shapeTimer);
        this.currShape = [];
        this.currColor = ItemColor.DEFAULT;
        this.scoreLabel.string = '' + this.score;

        //数据初始化后，图形开始下落
        this.setKeyboardActive(true);
        this.getNextShape();
    }

    //游戏暂停
    gameStop() {
        if (this.shapeTimer != null) {
            clearInterval(this.shapeTimer);
            this.setKeyboardActive(false);
        }
    }

    //继续游戏
    gameProceed() {
        this.shapeTimer = setInterval(() => {
            if (!this.shapeLeftOrRightOrDown([1, 0])) {
                clearInterval(this.shapeTimer);
                this.clearRowShape();
            }
        }, Config.shapeDownTime);
        this.setKeyboardActive(true);
    }

    //渲染数据
    shareGenerate() {
        for (var i = 0; i < Config.row; i++) {
            for (var j = 0; j < Config.col; j++) {
                var color = null
                if (this.items[i][j] > 0) {
                    color = this.colors[this.items[i][j] - 1];
                }
                this.shapes[i][j].getComponent(Sprite).spriteFrame = color;
            }
        }
    }
}


